import type {
  BaseStyleConfig,
  IPersonalizationItemConfig,
} from '../../../../types/interfaces'
import { ShortcutInput } from '../../../../components/shortcuts'
import { UserPref } from '../../../../lib/abstract'
import { PageHandler } from '../../../../lib/page_handler'
import { ToolKit } from '../../../../lib/utils/toolkit'
import { logger, VALID_RESULT } from '../../../../types/constants'
import { UserCenter } from '../../../user_center'

export interface IKeyModifiers {
  ctrl: boolean
  shift: boolean
  alt: boolean
  meta: boolean
}

export type ParsedShortcut = [modifiers: IKeyModifiers, key: string]

export class Shortcuts extends UserPref {
  readonly id = 'shortcuts'
  readonly name = 'Shortcuts'
  readonly styleConfigKey = 'shortcuts'
  readonly cssProperty = ''
  readonly cssValueSuffix = ''
  private isDialogOpen = false // 跟踪弹窗状态
  private userCenter: UserCenter | undefined
  private pageHandler: PageHandler = PageHandler.getInstance()
  private readonly defaultShortcut = 'Ctrl+Shift+Y'
  private useDefaultShortcut: boolean = false
  private activeListeners = new Map<string, {
    handler: (e: KeyboardEvent) => void
    cleanup: () => void
  }>()

  constructor(config: IPersonalizationItemConfig) {
    super(config)
  }

  createComponent(config: BaseStyleConfig, value: string, _mode: string, debouncedSave: (() => void) & {
    flush: () => void
  }): ShortcutInput {
    const id = this.generateId(config.styleVar)
    return new ShortcutInput({
      id,
      label: '窗口快捷键',
      shortcut: value,
      onInit: (instance) => {
        instance.setValue(value || this.defaultShortcut)
      },
      onChange: (value: string) => {
        this.cachedValues.set(id, value)
        debouncedSave()
        if (value === this.defaultShortcut) {
          this.useDefaultShortcut = true
          this.applyStyles()
        }
      },
    })
  }

  isChanged(newValue: string, oldValue: string): boolean {
    if (this.useDefaultShortcut) {
      this.useDefaultShortcut = false
      return false
    }

    return newValue !== oldValue
  }

  // 由于直接使用的是键盘输入值，所以不需要额外的校验逻辑（支持为空）
  handleCheck(_value: string): { status: ValidResultType, error: string } {
    return { status: VALID_RESULT.VALID.value, error: '' }
  }

  applyStyles(): void {
    // 先清理所有旧监听器
    this.clearAllListeners()

    this.getInstanceIds().forEach((id) => {
      const targetShortcut = this.cachedValues.get(id) as string
      const [modifiers, key] = this.parseShortcut(targetShortcut)

      const handler = ToolKit.func.throttle(this.createHandler(modifiers, key), 300)

      // 创建监听器并保存引用
      document.addEventListener('keydown', handler, true)
      this.activeListeners.set(id, {
        handler,
        cleanup: () => document.removeEventListener('keydown', handler, true),
      })
    })
  }

  /**
   * 检查事件是否匹配指定的快捷键
   */
  private checkMatch(e: KeyboardEvent, modifiers: IKeyModifiers, key: string): boolean {
    return (
      modifiers.ctrl === e.ctrlKey
      && modifiers.shift === e.shiftKey
      && modifiers.alt === e.altKey
      && modifiers.meta === e.metaKey
      && e.key.toUpperCase() === key.toUpperCase()
    )
  }

  /**
   * 创建事件处理函数
   */
  private createHandler(modifiers: IKeyModifiers, key: string) {
    return async (e: KeyboardEvent) => {
      if (this.checkMatch(e, modifiers, key)) {
        e.preventDefault()

        await this.toggleUserCenter()
      }
    }
  }

  /**
   * 清理所有已注册的事件监听器
   */
  private clearAllListeners(): void {
    this.activeListeners.forEach(({ cleanup }, id) => {
      try {
        cleanup()
      }
      catch (err: any) {
        logger.error(`[${this.name}] 移除监听器失败 - ${id}:`, err)
      }
    })

    this.activeListeners.clear() // 必须清空 Map
  }

  /**
   * 解析快捷键字符串
   * @example "Ctrl+Shift+Y" => { modifiers: {ctrl:true, shift:true}, key: "Y" }
   */
  private parseShortcut(shortcut: string): ParsedShortcut {
    if (!shortcut)
      return [{ ctrl: false, shift: false, alt: false, meta: false }, '']

    const parts = shortcut.split('+')
    const key = parts.pop()! // 最后一个部分是主键

    const modifiers = {
      ctrl: parts.includes('Ctrl'),
      shift: parts.includes('Shift'),
      alt: parts.includes('Alt'),
      meta: parts.includes('Meta'),
    }

    return [modifiers, key]
  }

  /**
   * 切换用户中心弹窗状态
   * 1. 弹窗已打开：关闭弹窗
   * 2. 弹窗已关闭：打开弹窗
   */
  private async toggleUserCenter(): Promise<void> {
    if (!this.userCenter) {
      this.userCenter = await UserCenter.create()
    }

    if (this.isDialogOpen) {
      // 关闭弹窗
      this.pageHandler.ui.toast.close()
      this.isDialogOpen = false
    }
    else {
      // 打开弹窗
      this.userCenter.showDialog()
      this.isDialogOpen = true
    }
  }
}
